// 防抖
function debounce(fn, time) {
    let timer = null
    return function (...args) {
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn.call(this, ...args)
        }, time)
    }
}

// 截流
function throtte(fn,time) {
    let timer = null
    return function (...args) {
        if (!timer) {
            fn.call(this, ...args)
            timer = setTimeout(() => {     
                timer = null;
            }, time)
        };
    }
}

// 柯里化 加法
const mul = (x) => {
    let sum = x
    let curried = (y) => {
        sum = sum * y
        return curried
    }
    curried.valueOf = () => sum
    return curried
}

console.log(mul(1)) //1
console.log(mul(1)(2))//2
console.log(mul(1)(2)(3))//6
console.log(mul(1)(2)(3)(4))//24

// 柯里化 加法
var add = function (m) {
    var temp = function (n) {
        return add(m + n);
    }
    temp.toString = function () {
        return m;
    }
    return temp;
};
console.log(add(3)(4)(5)); // 12
console.log(add(3)(6)(9)(25)); // 43

// compose
function compose(fns) {
    return function (data) {
        return fns.reduce((pre, next) => {
            return next(pre)
        }, data)
    }
}

// curry
function curry(fn) {
    return function curried(...args) {
        if (fn.length === args.length) {
            return fn.call(this, ...args)
        } else {
            return function (...args1) {
                return curried(...[...args, ...args1])
            }
        }
    }
}

Function.prototype.myApply = function (context = window, args) {
    if (typeof this !== "function") {
        return new Error("not myself")
    }
    let x = Symbol();
    context[x] = this
    let result = context[x](...args)
    delete context[x]
    return result
}


Function.prototype.myCall = function (context = window, args) {
    if (typeof this !== "function") {
        return new Error("not myself")
    }
    let x = Symbol();
    context[x] = this
    let result
    if (Array.isArray(args)) {
        result = context[x](args)
    } else {
        result = context[x]()
    }
    delete context[x]
    return result
}



Function.prototype.myBind = function (context = window, args) {
    if (typeof this !== "function") {
        return new Error("not myself")
    }
    return function (...args) {
        let x = Symbol();
        context[x] = this
        let result = context[x](...args)
        delete context[x]
        return result
    }
}
